import { useState, useCallback } from 'react';
import {
  TenantUser,
  TenantRole,
  TenantPermission,
  TenantDepartment,
  TenantTeam,
  TenantPermissionContext,
  TenantPermissionResult,
  PermissionCondition,
} from '../../types/tenant';

/**
 * 多租户权限管理Hook
 * 提供租户权限验证、权限查询等功能
 */
export const useTenantPermissions = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  /**
   * 验证用户在指定租户下的权限
   */
  const validatePermission = useCallback(async (
    context: TenantPermissionContext
  ): Promise<TenantPermissionResult> => {
    setLoading(true);
    setError(null);

    try {
      // 1. 获取用户在租户下的完整权限
      const userPermissions = await getUserTenantPermissions(
        context.userId,
        context.tenantId
      );

      // 2. 检查是否有匹配的权限
      const matchingPermissions = userPermissions.filter(permission =>
        isPermissionMatching(permission, context)
      );

      if (matchingPermissions.length === 0) {
        return {
          granted: false,
          reason: 'NO_MATCHING_PERMISSION',
          missingPermissions: [`${context.resourceData?.resource}:${context.operationContext?.action}`],
        };
      }

      // 3. 评估权限条件
      for (const permission of matchingPermissions) {
        const conditionResult = await evaluatePermissionConditions(
          permission,
          context
        );

        if (conditionResult.granted) {
          return {
            granted: true,
            scope: permission.scope,
            conditions: permission.conditions,
          };
        }
      }

      return {
        granted: false,
        reason: 'CONDITION_NOT_MET',
      };

    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '权限验证失败';
      setError(errorMessage);
      console.error('权限验证失败:', err);
      return {
        granted: false,
        reason: 'VALIDATION_ERROR',
      };
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * 批量验证权限
   */
  const batchValidatePermissions = useCallback(async (
    userId: string,
    tenantId: string,
    permissions: Array<{ resource: string; action: string; context?: Record<string, any> }>
  ): Promise<Record<string, boolean>> => {
    setLoading(true);
    setError(null);

    try {
      const results: Record<string, boolean> = {};

      for (const permission of permissions) {
        const context: TenantPermissionContext = {
          userId,
          tenantId,
          resourceData: { resource: permission.resource, ...permission.context },
          operationContext: { action: permission.action },
          userContext: {},
          tenantContext: { tenantId },
        };

        const result = await validatePermission(context);
        const key = `${permission.resource}:${permission.action}`;
        results[key] = result.granted;
      }

      return results;
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '批量权限验证失败';
      setError(errorMessage);
      console.error('批量权限验证失败:', err);
      return {};
    } finally {
      setLoading(false);
    }
  }, [validatePermission]);

  /**
   * 获取用户在租户下的所有权限
   */
  const getUserPermissions = useCallback(async (
    userId: string,
    tenantId: string
  ): Promise<TenantPermission[]> => {
    setLoading(true);
    setError(null);

    try {
      return await getUserTenantPermissions(userId, tenantId);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '获取用户权限失败';
      setError(errorMessage);
      console.error('获取用户权限失败:', err);
      return [];
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * 获取用户在租户下的所有角色
   */
  const getUserRoles = useCallback(async (
    userId: string,
    tenantId: string
  ): Promise<TenantRole[]> => {
    setLoading(true);
    setError(null);

    try {
      const user = await getTenantUser(userId, tenantId);
      if (!user) {
        return [];
      }

      return await getUserTenantRoles(user, tenantId);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : '获取用户角色失败';
      setError(errorMessage);
      console.error('获取用户角色失败:', err);
      return [];
    } finally {
      setLoading(false);
    }
  }, []);

  return {
    loading,
    error,
    validatePermission,
    batchValidatePermissions,
    getUserPermissions,
    getUserRoles,
  };
};

// ============= 辅助函数 =============

/**
 * 获取用户在租户下的所有权限
 */
async function getUserTenantPermissions(
  userId: string,
  tenantId: string
): Promise<TenantPermission[]> {
  try {
    // 1. 获取用户信息
    const user = await getTenantUser(userId, tenantId);
    if (!user) {
      return [];
    }

    // 2. 获取用户的所有角色
    const allRoles = await getUserTenantRoles(user, tenantId);

    // 3. 收集所有权限
    const allPermissions = new Set<TenantPermission>();

    for (const role of allRoles) {
      role.permissions.forEach(permission => {
        // 确保权限属于当前租户或为全局权限
        if (!permission.tenantId || permission.tenantId === tenantId) {
          allPermissions.add(permission);
        }
      });
    }

    return Array.from(allPermissions);

  } catch (error) {
    console.error('获取用户租户权限失败:', error);
    return [];
  }
}

/**
 * 获取用户在租户下的所有角色
 */
async function getUserTenantRoles(
  user: TenantUser,
  tenantId: string
): Promise<TenantRole[]> {
  const roles: TenantRole[] = [];

  try {
    // 1. 用户直接分配的角色
    const directRoles = await getRolesByIds(user.roles, tenantId);
    roles.push(...directRoles);

    // 2. 从团队继承的角色 - 已移除团队角色功能

    // 3. 从部门继承的角色 - 已移除部门角色功能

    // 去重并返回
    return deduplicateRoles(roles);

  } catch (error) {
    console.error('获取用户租户角色失败:', error);
    return [];
  }
}

/**
 * 获取用户团队角色 - 已移除团队角色功能
 */
async function getUserTeamRoles(
  user: TenantUser,
  tenantId: string
): Promise<TenantRole[]> {
  // 团队角色功能已移除，返回空数组
  return [];
}

/**
 * 获取部门角色 - 已移除部门角色功能
 */
async function getUserDepartmentRoles(
  user: TenantUser,
  tenantId: string
): Promise<TenantRole[]> {
  // 部门角色功能已移除，返回空数组
  return [];
}

/**
 * 检查权限是否匹配
 */
function isPermissionMatching(
  permission: TenantPermission,
  context: TenantPermissionContext
): boolean {
  const resourceType = context.resourceData?.resource;
  const action = context.operationContext?.action;

  if (!resourceType || !action) {
    return false;
  }

  return (
    permission.resource === resourceType &&
    permission.action === action
  );
}

/**
 * 评估权限条件
 */
async function evaluatePermissionConditions(
  permission: TenantPermission,
  context: TenantPermissionContext
): Promise<TenantPermissionResult> {
  // 如果没有条件，直接通过
  if (!permission.conditions || permission.conditions.length === 0) {
    return { granted: true };
  }

  try {
    // 根据权限范围进行初步检查
    const scopeResult = await evaluatePermissionScope(permission.scope, context);
    if (!scopeResult.granted) {
      return scopeResult;
    }

    // 评估自定义条件
    for (const condition of permission.conditions) {
      const conditionResult = await evaluateCondition(condition, context);
      if (!conditionResult) {
        return {
          granted: false,
          reason: `CONDITION_FAILED: ${condition.field} ${condition.operator} ${condition.value}`,
        };
      }
    }

    return { granted: true };

  } catch (error) {
    console.error('评估权限条件失败:', error);
    return {
      granted: false,
      reason: 'CONDITION_EVALUATION_ERROR',
    };
  }
}

/**
 * 评估权限范围
 */
async function evaluatePermissionScope(
  scope: string,
  context: TenantPermissionContext
): Promise<TenantPermissionResult> {
  switch (scope) {
    case 'global':
      return { granted: true };

    case 'tenant':
      return {
        granted: context.tenantId === context.tenantContext?.tenantId,
        reason: context.tenantId !== context.tenantContext?.tenantId ? 'WRONG_TENANT' : undefined,
      };

    case 'department':
      return await evaluateDepartmentScope(context);

    case 'team':
      return await evaluateTeamScope(context);

    case 'owner':
      return await evaluateOwnerScope(context);

    case 'custom':
      // 自定义范围需要通过条件来评估
      return { granted: true };

    default:
      return {
        granted: false,
        reason: `UNKNOWN_SCOPE: ${scope}`,
      };
  }
}

/**
 * 评估部门范围权限
 */
async function evaluateDepartmentScope(
  context: TenantPermissionContext
): Promise<TenantPermissionResult> {
  const user = await getTenantUser(context.userId, context.tenantId);
  const targetDepartmentId = context.resourceData?.departmentId;

  if (!user?.departmentId || !targetDepartmentId) {
    return {
      granted: false,
      reason: 'MISSING_DEPARTMENT_INFO',
    };
  }

  // 检查是否为同一部门或子部门
  const isSameDepartment = user.departmentId === targetDepartmentId;
  const isParentDept = await isParentDepartment(
    user.departmentId,
    targetDepartmentId,
    context.tenantId
  );

  return {
    granted: isSameDepartment || isParentDept,
    reason: !(isSameDepartment || isParentDept) ? 'DIFFERENT_DEPARTMENT' : undefined,
  };
}

/**
 * 评估团队范围权限
 */
async function evaluateTeamScope(
  context: TenantPermissionContext
): Promise<TenantPermissionResult> {
  const user = await getTenantUser(context.userId, context.tenantId);
  const targetTeamId = context.resourceData?.teamId;

  if (!user?.teamIds?.length || !targetTeamId) {
    return {
      granted: false,
      reason: 'MISSING_TEAM_INFO',
    };
  }

  const isInSameTeam = user.teamIds.includes(targetTeamId);
  return {
    granted: isInSameTeam,
    reason: !isInSameTeam ? 'DIFFERENT_TEAM' : undefined,
  };
}

/**
 * 评估所有者范围权限
 */
async function evaluateOwnerScope(
  context: TenantPermissionContext
): Promise<TenantPermissionResult> {
  const resourceOwnerId = context.resourceData?.ownerId;

  if (!resourceOwnerId) {
    return {
      granted: false,
      reason: 'MISSING_OWNER_INFO',
    };
  }

  const isOwner = context.userId === resourceOwnerId;
  return {
    granted: isOwner,
    reason: !isOwner ? 'NOT_OWNER' : undefined,
  };
}

/**
 * 评估单个条件
 */
async function evaluateCondition(
  condition: PermissionCondition,
  context: TenantPermissionContext
): Promise<boolean> {
  try {
    let actualValue: any;

    // 获取实际值
    if (condition.contextField) {
      actualValue = getContextValue(context, condition.contextField);
    } else {
      actualValue = context.resourceData?.[condition.field];
    }

    // 执行条件比较
    return compareValues(actualValue, condition.operator, condition.value);

  } catch (error) {
    console.error('评估条件失败:', error);
    return false;
  }
}

/**
 * 从上下文获取值
 */
function getContextValue(context: TenantPermissionContext, fieldPath: string): any {
  const parts = fieldPath.split('.');
  let value: any = context;

  for (const part of parts) {
    if (value && typeof value === 'object') {
      value = value[part];
    } else {
      return undefined;
    }
  }

  return value;
}

/**
 * 比较值
 */
function compareValues(actual: any, operator: string, expected: any): boolean {
  switch (operator) {
    case '=':
      return actual === expected;
    case '!=':
      return actual !== expected;
    case '>':
      return actual > expected;
    case '<':
      return actual < expected;
    case 'in':
      return Array.isArray(expected) && expected.includes(actual);
    case 'not_in':
      return Array.isArray(expected) && !expected.includes(actual);
    case 'contains':
      return typeof actual === 'string' && typeof expected === 'string' && actual.includes(expected);
    default:
      return false;
  }
}

// ============= API调用函数（需要实现） =============

async function getTenantUser(userId: string, tenantId: string): Promise<TenantUser | null> {
  // TODO: 调用API获取租户用户信息
  return null;
}

async function getRolesByIds(roleIds: string[], tenantId: string): Promise<TenantRole[]> {
  // TODO: 调用API获取角色信息
  return [];
}

async function getUserTeams(teamIds: string[], tenantId: string): Promise<TenantTeam[]> {
  // TODO: 调用API获取用户团队信息
  return [];
}

async function getTenantDepartment(departmentId: string, tenantId: string): Promise<TenantDepartment | null> {
  // TODO: 调用API获取部门信息
  return null;
}

async function getParentTeamRoles(parentTeamId: string, tenantId: string): Promise<TenantRole[]> {
  // 团队角色功能已移除，返回空数组
  return [];
}

async function getParentDepartmentRoles(parentDeptId: string, tenantId: string): Promise<TenantRole[]> {
  // 部门角色功能已移除，返回空数组
  return [];
}

async function isParentDepartment(userDeptId: string, targetDeptId: string, tenantId: string): Promise<boolean> {
  // TODO: 检查是否为父部门
  return false;
}

function deduplicateRoles(roles: TenantRole[]): TenantRole[] {
  const seen = new Set<string>();
  return roles.filter(role => {
    if (seen.has(role.id)) {
      return false;
    }
    seen.add(role.id);
    return true;
  });
}

// ============= 便捷函数导出 =============

/**
 * 简单权限验证函数
 */
export const validateTenantPermission = async (
  userId: string,
  tenantId: string,
  resource: string,
  action: string,
  resourceContext?: Record<string, any>
): Promise<boolean> => {
  const context: TenantPermissionContext = {
    userId,
    tenantId,
    resourceData: { resource, ...resourceContext },
    operationContext: { action },
    userContext: {},
    tenantContext: { tenantId },
  };

  const userPermissions = await getUserTenantPermissions(userId, tenantId);
  const matchingPermissions = userPermissions.filter(permission =>
    isPermissionMatching(permission, context)
  );

  if (matchingPermissions.length === 0) {
    return false;
  }

  for (const permission of matchingPermissions) {
    const conditionResult = await evaluatePermissionConditions(permission, context);
    if (conditionResult.granted) {
      return true;
    }
  }

  return false;
};

/**
 * 批量权限验证函数
 */
export const batchValidateTenantPermissions = async (
  userId: string,
  tenantId: string,
  permissions: Array<{ resource: string; action: string; context?: Record<string, any> }>
): Promise<Record<string, boolean>> => {
  const results: Record<string, boolean> = {};

  for (const permission of permissions) {
    const key = `${permission.resource}:${permission.action}`;
    results[key] = await validateTenantPermission(
      userId,
      tenantId,
      permission.resource,
      permission.action,
      permission.context
    );
  }

  return results;
};